package org.icnmasjid.member.webapp.action;

import java.security.InvalidKeyException;
import java.security.InvalidParameterException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.icnmasjid.member.Constants;
import org.icnmasjid.member.model.MemberInformation;
import org.icnmasjid.member.model.Person;
import org.icnmasjid.member.model.PersonRelation;
import org.icnmasjid.member.model.RelationshipType;
import org.icnmasjid.member.util.DesEncrypter;
import org.springframework.validation.BindException;
import org.springframework.web.servlet.ModelAndView;

public class PersonRelationshipFormController extends BasePersonFormController {
    public PersonRelationshipFormController() {
        setCommandName("person");
        setCommandClass(Person.class);
    }

    protected Object formBackingObject(HttpServletRequest request)
    throws Exception {
        String primaryPersonId = request.getParameter("primaryPersonId");
        String personId = request.getParameter("personId");
        Person person = null;
        if ( StringUtils.isEmpty(primaryPersonId) ) {
        	throw new InvalidParameterException("primaryPersonId is required");
        }
        if ( !StringUtils.isEmpty(personId)) {
            person = personManager.getPerson(personId);
            // security check
            if (personManager.getPerson(primaryPersonId).getPersonRelation(person) == null) {
            	throw new InvalidParameterException("Invalid Dependent Id");
            }
        }
        if ( person == null ) {
        	// copy primary's info
            person = new Person(personManager.getPerson(primaryPersonId));
            // erase unique info
            person.setFirstName(null);
            person.setEmail(null);
            person.setEmail2(null);
            person.setPhoneWork(null);
            person.setPhoneMobile(null);
            person.setPhoneFax(null);
            person.setEmployerName(null);
            person.setPersonStatus(null);
            person.setPrimaryPerson(Boolean.FALSE);
        }
        if ( isRestricted(request) ) {
        	String passKey = request.getParameter("passKey");
        	if ( passKey == null || !new DesEncrypter(Constants.CRYPTO_KEY).decrypt(passKey).equals(primaryPersonId)) {
        		throw new InvalidKeyException("Invalid key");
        	}

        }
        return person;
    }

    @Override
    protected Map referenceData(HttpServletRequest request) throws Exception {
    	Map map = super.referenceData(request);
    	if ( map == null ) {
    		map = new HashMap();
    	}
    	map.put("relationshipTypes", manager.getObjects(org.icnmasjid.member.model.RelationshipType.class));
    	map.put("primaryPersonId", request.getParameter("primaryPersonId"));
    	if ( StringUtils.isNotBlank(request.getParameter("primaryPersonId")) ) {
    		map.put("primaryPerson", personManager.getPerson(request.getParameter("primaryPersonId")));
    	}
    	return map;
    }

    public ModelAndView onSubmit(HttpServletRequest request,
                                 HttpServletResponse response, Object command,
                                 BindException errors)
    throws Exception {
        if (log.isDebugEnabled()) {
            log.debug("entering 'onSubmit' method...");
        }

        Person person = (Person) command;
        boolean isNew = (person.getPersonId() == null);
        Locale locale = request.getLocale();
    	String primaryPersonId = request.getParameter("primaryPersonId");
    	Person primaryPerson   = personManager.getPerson(primaryPersonId);

    	primaryPerson.setUserUpdated(person.getUserUpdated()+1);

        if (request.getParameter("delete") != null) {
        	PersonRelation relatedPersonRelation = primaryPerson.getPersonRelation(person);
        	System.out.println("remove successful1: " + primaryPerson.getPersonRelations().remove(relatedPersonRelation));
        	System.out.println("remove successful2: " + person.getParentPersonRelations().remove(relatedPersonRelation));
        	//manager.removeObject(PersonRelation.class, relatedPersonRelation.getId());        	
            personManager.savePerson(primaryPerson);
            personManager.removePerson(person.getPersonId().toString());
            saveMessage(request, getText("person.deleted", locale));
            HashMap map = new HashMap();
            map.put("personId", primaryPersonId);
            if ( isRestricted(request) ) {
            	map.put("passKey", request.getParameter("passKey"));
            }
            return new ModelAndView(isRestricted(request) ? "redirect:editPersonRestricted.html" :"redirect:editPerson.html", map);
        } else if ("addRole".equals(request.getParameter("action"))) {
        	return addRole(request, response, person);
        } else if ("deleteRole".equals(request.getParameter("action"))) {
        	return deleteRole(request, response, person);
        } else {
        	RelationshipType rt =
        	(RelationshipType)manager.getObject(
        			org.icnmasjid.member.model.RelationshipType.class,
        			Integer.valueOf(request.getParameter("relationshipTypeId")));
        	if ( isNew ) {
	        	PersonRelation pr = new PersonRelation();
	        	pr.setPerson(primaryPerson);
	        	pr.setRelatedPerson(person);
	        	pr.setRelationshipType(rt);

	        	primaryPerson.getPersonRelations().add(pr);
	        	//manager.saveObject(pr);
        	} else {
        		// set the relationship type
        		// manual binding
        		PersonRelation pr = primaryPerson.getPersonRelation(person);
        		pr.setRelationshipType(rt);
        	}
            personManager.savePerson(person);

            String key = (isNew) ? "person.added" : "person.updated";
            saveMessage(request, getText(key, locale));
        }
        HashMap map = new HashMap();
        map.put("personId", primaryPerson.getPersonId());
        String viewName = "redirect:editPerson.html";
        if ( isRestricted(request) ) {
        	map.put("passKey", request.getParameter("passKey"));
        	viewName = "redirect:editPersonRestricted.html";
        }
        return new ModelAndView(viewName , map);
    }

    private boolean isRestricted(HttpServletRequest request) {
    	return request.getRequestURI().indexOf("Restricted") >= 0;
    }
    
    @Override
    protected void onBindAndValidate(HttpServletRequest request, Object command, BindException errors) throws Exception {
    	super.onBindAndValidate(request, command, errors);
    	Person p = (Person)command;
    	// bind the memberships manually
    	Iterator<MemberInformation> i = p.getMemberInformations().iterator();
    	while ( i.hasNext() ) {
    		if ( !p.getMemberYear().contains(i.next().getYearOfMembership()) ) {
    			i.remove();
    		}
    	}
    	for ( int year: p.getMemberYear() ) {
    		p.setMember(true, year);
    	}
    }

}
